const { resolve } = require('path')
const fse = require('fs-extra')
const { resolvePost, extractExt } = require('./utils')
const multiparty = require('multiparty')
const UPLOAD_DIR = resolve(__dirname, 'target')

module.exports = class {
  // 处理上传文件块
  async handleFormData(req, res) {
    console.log('处理上传文件块 handleFormData')
    const multipart = new multiparty.Form()
    multipart.parse(req, async (err, fields, files) => {
      if (err) {
        console.error(err)
        res.status = 500
        res.end('upload error')
        return
      }
      const [chunk] = files.chunk
      const [chunkHash] = fields.chunkHash
      const [fileHash] = fields.fileHash
      const [fileName] = fields.fileName
      // filePath: 生成的文件
      const filePath = resolve(UPLOAD_DIR, `${fileHash}${extractExt(fileName)}`)
      // chunkDir: /target/hsah串文件夹
      const chunkDir = resolve(UPLOAD_DIR, fileHash)
      if (fse.existsSync(filePath)) {
        res.end('already exists')
        return
      }

      if (!fse.existsSync(chunkDir)) {
        // target下没有文件目录
        await fse.mkdirs(chunkDir)
      }
      await fse.move(chunk.path, resolve(chunkDir, chunkHash))
      res.end(
        JSON.stringify({
          success: true,
          message: 'upload success',
        })
      )
    })
  }

  // 校验服务端是否拥有文件
  async handleVerifyUpload(req, res) {
    console.log('校验服务端是否拥有文件')
    const { fileName, hash } = await resolvePost(req)
    const ext = extractExt(fileName)
    // 以hash.后缀命名的文件
    const filePath = resolve(UPLOAD_DIR, `${hash}${ext}`)
    if (fse.existsSync(filePath)) {
      // 已存在文件
      res.end(
        JSON.stringify({
          shouldUpload: false,
        })
      )
    } else {
      // 以hash命名的文件夹
      const chunkDir = resolve(UPLOAD_DIR, hash)
      console.log(chunkDir, '校验文件 chunkdir')
      let exists = await fse.pathExists(chunkDir)
      let uploadedList
      if (exists) {
        const chunkPaths = await fse.readdir(chunkDir)
        uploadedList = chunkPaths
      } else {
        uploadedList = []
      }
      res.end(
        JSON.stringify({
          shouldUpload: true,
          uploadedList,
        })
      )
    }
  }

  // 合并文件块
  async handleMerge(req, res) {
    const data = await resolvePost(req)
    const { size, fileHash, fileName } = data
    const ext = extractExt(fileName)
    const filePath = resolve(UPLOAD_DIR, `${fileHash}${ext}`)
    await mergeFileChunk(filePath, fileHash, size)
    res.end(JSON.stringify('merge success'))
  }
}

// 合并文件块
const mergeFileChunk = async (filePath, fileName, size) => {
  // 拿到文件块目录
  const chunkDir = resolve(UPLOAD_DIR, fileName)
  // 拿到文件块文件夹下面的文件块
  const chunkPaths = await fse.readdir(chunkDir)
  chunkPaths.sort((a, b) => a.split('-')[1] - b.split('-')[1])
  await Promise.all(
    chunkPaths.map((chunkPath, index) =>
      pipeStream(
        resolve(chunkDir, chunkPath),
        fse.createWriteStream(filePath, {
          start: index * size,
          end: (index + 1) * size,
        })
      )
    )
  )
  // 删除文件块文件夹
  // fse.rmdirSync(chunkDir);
}
// 文件块读写
const pipeStream = (path, writeStream) =>
  new Promise((resolve) => {
    // 读文件块目录下文件块的内容
    const readStream = fse.createReadStream(path)
    readStream.on('end', () => {
      // 删除文件块
      // fse.removeSync(path);
      resolve()
    })
    readStream.pipe(writeStream)
  })
